#!/usr/bin/env python
# encoding: utf-8


"""
@file: zhishiyuan.py
@time: 2016/12/8 下午12:39
"""
# 知识元
from mathsolver.functions.base import *
from sympy import pi, sin, cos, simplify, symbols, sqrt, expand, acos, expand_trig, collect_const, solveset
from mathsolver.functions.budengshi import common_opers as co
from mathsolver.functions.sanjiao.sanjiao_objects import SanJiaoXing
from mathsolver.functions.sanjiao import sanjiaoxing_utils as san_utils
from mathsolver.functions.sanjiao import sanjiao_utils
import re
from operator import itemgetter
from mathsolver.functions.sanjiao import triangle_constant as t_const
from mathsolver.functions.sanjiao import sanjiaoxing_utils as sjx_u


# 已知两边一夹角求三角形面积
class ZhiShiYuan005(BaseFunction):
    def solver(self, *args):
        return self


# 6-1 已知一组角与对边求三角形面积的最大值
class ZhiShiYuan006Sub01(BaseFunction):
    def solver(self, *args):
        # eqs = args[0]
        eqs = sjx_u.known_triangle_eqs(self.known)  # 得出已知条件
        # values_list = co.solve_poly_eqs(eqs)
        values_list = co.isolve_eqs(eqs)
        angle_value = ''
        side_value = ''
        angle_symb = None
        side_symb = None
        for values in values_list:
            for symb, symb_v in values:
                if str(symb) in ('a', 'b', 'c'):
                    side_symb = symb
                    side_value = symb_v
                elif str(symb) in ('A', 'B', 'C'):
                    angle_symb = symb
                    angle_value = symb_v
        if not angle_value or not side_value:
            raise Exception('solve error')
        if str(angle_symb).lower() == str(side_symb).lower() and angle_value.is_real and side_value.is_real:
            pass
        else:
            raise Exception('Can not solve the question')
        area_expr = sin(angle_symb) * side_symb ** 2 / (4 - 4 * cos(angle_symb))
        self.steps.append(['由题意可知', 'S <= ' + new_latex(area_expr)])
        max_area = sin(angle_value) * side_value ** 2 / (4 - 4 * cos(angle_value))
        self.steps.append(['所以求得面积最大值为', new_latex(max_area)])
        self.output.append(BaseNumber(max_area))
        return self


# 6-2 已知两边边长，求三角形面积的最大值---题型
class ZhiShiYuan006Sub02(BaseFunction):
    def solver(self, *args):
        eqs = args[0]
        values_list = co.solve_poly_eqs(eqs)
        values = values_list[0]
        v1, v2 = values
        one_side, one_side_value = v1
        other_side, other_side_value = v2
        max_are = one_side_value * other_side_value / 2
        self.output.append(BaseNumber(max_are))
        return self


# 6- 3 已知等腰三角形腰上的中线的长度为a,求三角形面积的最大值---元函数
# 输入：等腰三角形，腰上的中线的长度a
# 输出：三角形面积的最大值
class ZhiShiYuan006Sub03(BaseFunction):
    def solver(self, *args):
        v = args[0].sympify()
        xx = sympify('x')
        self.steps.append(['设腰长为' + new_latex(2 * xx), '顶角为E'])
        max_area = v ** 2 * 2 / 3
        self.output.append(BaseNumber(max_area))
        return self


# 6-4.已知三角形两条中线的长度，求三角形面积的最大值
class ZhiShiYuan006Sub04(BaseFunction):
    def solver(self, *args):
        eqs = args[0]
        values_list = co.solve_poly_eqs(eqs)
        values = values_list[0]
        v1, v2 = values
        _, x_v = v1
        _, y_v = v2
        self.steps.append(['两中线的夹角为 h , 其补角大小为%s - h' % new_latex(pi)])
        self.steps.append(['设x, y 代表两条中线的值', ''])
        xx, yy, e = symbols('x, y, e')
        step1 = 2 * ((2 * xx / 3) * yy / 3 * sin(e) + (2 * xx / 3) * (2 * yy / 3) * sin(pi - e))
        step2 = 2 * ((2 * xx * yy) / 9 * sin(e) + (4 * xx * yy * sin(e)) / 9)
        step3 = (6 * xx * yy * sin(e)) / 9
        self.steps.append(['S = ', new_latex(step1)])
        self.steps.append(['  = ', new_latex(step2)])
        self.steps.append(['  = ', new_latex(step3)])
        max_area = 6 * x_v * y_v / 9
        self.steps.append(['\\because %s <= 1' % new_latex(sin(e)), ''])
        self.steps.append(['\\therefore S = ' + new_latex(step3), '<=' + new_latex(max_area)])
        self.output.append(BaseNumber(max_area))
        return self


# 6-5.已知边a=m,b+c=n求三角形面积的最大值
class ZhiShiYuan006Sub05(BaseFunction):
    def solver(self, *args):
        eq1, eq2 = args[0].sympify()
        eq1_f = eq1[0] - eq1[1]
        eq1_symbs = eq1_f.free_symbols
        eq2_f = eq2[0] - eq2[1]
        eq2_symbs = eq2_f.free_symbols
        if len(eq1_symbs) == 1:
            single_side = list(eq1_symbs)[0]
            m_value = solve(eq1_f)[0]
            other_sides = list(eq2_symbs)
            n_value = solve(eq2_f, other_sides[0] + other_sides[1])
        else:
            single_side = list(eq2_symbs)[0]
            m_value = solve(eq2_f)[0]
            other_sides = list(eq1_symbs)
            n_value = solve(eq1_f, other_sides[0] + other_sides[1])
        point1, point2 = map(lambda _: _.upper(), map(str, other_sides))
        self.steps.append(
            ['结合椭圆的性质。可以得到点%s, %s 均在焦点上， 点%s的焦距为 %s, 长轴为%s的椭圆上的一动点' %
             (point1, point2, str(single_side).upper(), new_latex(m_value), new_latex(n_value)),
             ''])
        self.steps.append(
            ['结合椭圆的图像可以得知当%s=%s=%s/2时（A在长轴端点）取得面积的最大值' %
             (new_latex(other_sides[0]), new_latex(other_sides[1]), new_latex(n_value)), ''])
        max_area = (m_value * sqrt(n_value ** 2 - m_value ** 2)) / 4
        self.steps.append(['所以面积的最大值= %s' % new_latex(max_area),
                           ' 当且仅当%s=%s=%s/2时取得' % (new_latex(other_sides[0]), new_latex(other_sides[1]), new_latex(n_value))])
        self.output.append(BaseNumber(max_area))
        return self


# 6-6.已知某边长，另外两条边平方和 求面积最值
class ZhiShiYuan006Sub06(BaseFunction):
    def solver(self, *args):
        eq1, eq2 = args[0].sympify()
        eq1_f = eq1[0] - eq1[1]
        eq1_symbs = eq1_f.free_symbols
        eq2_f = eq2[0] - eq2[1]
        eq2_symbs = eq2_f.free_symbols
        if len(eq1_symbs) == 1:
            n_value = solve(eq1_f)[0]
            other_sides = list(eq2_symbs)
            m_value = solve(eq2_f, other_sides[0] ** 2 + other_sides[1] ** 2)
        else:
            n_value = solve(eq2_f)[0]
            other_sides = list(eq1_symbs)
            m_value = solve(eq1_f, other_sides[0] ** 2 + other_sides[1] ** 2)
        max_area = sqrt(2 * m_value * n_value ** 2 - n_value ** 4) / 4
        self.steps.append(['面积最值为:', ''])
        self.output.append(BaseNumber(max_area))
        return self


# 6-7.已知边a=m.b=nc求三角形面积的最大值（其中m,n为常数）
class ZhiShiYuan006Sub07(BaseFunction):
    def solver(self, *args):
        eq1, eq2 = args[0].sympify()
        eq1_f = eq1[0] - eq1[1]
        eq1_symbs = eq1_f.free_symbols
        eq2_f = eq2[0] - eq2[1]
        eq2_symbs = eq2_f.free_symbols
        if len(eq1_symbs) == 1:
            m_value = solve(eq1_f)[0]
            other_sides = list(eq2_symbs)
            n_value = solve(eq2_f, other_sides[0])[0].coeff(other_sides[1])
        else:
            m_value = solve(eq2_f)[0]
            other_sides = list(eq1_symbs)
            n_value = solve(eq1_f, other_sides[0])[0].coeff(other_sides[1])
        max_area = 2 * m_value ** 2 * n_value / abs(n_value ** 2 - 1)
        self.output.append(BaseNumber(max_area))
        self.steps.append(['面积最值为:', new_latex(max_area)])
        return self


# 6-8.已知两边之和求三角形面积的最大值
class ZhiShiYuan006Sub08(BaseFunction):
    def solver(self, *args):
        l_expr, r_expr = args[0].sympify()
        eq_f = l_expr - r_expr
        side1, side2 = eq_f.free_symbols
        other_side = list(FiniteSet(sympify('a'), sympify('b'), sympify('c')) - FiniteSet(side1, side2))[0]
        m_value = abs(solve(eq_f, side1 + side2)[0])
        self.steps.append([r'{S_{\Delta ABC}} = ',
                           new_latex(sympify(1) / 2 * side1 * side2 * sin(str(other_side).upper())) + ' <= ' +
                           new_latex(sympify(1) / 2 * side1 * side2) + r'当且仅当角%s = {90^ \circ } 时取得等号' % str(
                               other_side).upper()])
        self.steps.append(['由均值不等式可得 ', new_latex(side1 * side2) + ' <= \frac{{{%s^2}}}{4}' % new_latex(m_value)])
        self.steps.append(['面积的最大值是{%s^2}' % new_latex(m_value),
                           r'当且仅当角%s = {90^ \circ }, %s=%s=%s/2' % (
                               str(other_side).upper(), new_latex(side1), new_latex(side2), new_latex(m_value))])
        max_area = m_value ** 2 / 8
        self.output.append(BaseNumber(max_area))
        return self


# 6-9.已知S=c^{2}-(a-b)^{2}，a+b=m，求三角形面积的最大值。
# 529313 已知△ABC的三边a,b,c和其面积S满足S=c^{2}-(a-b)^{2},a+b=2,则S的最大值为(）
class ZhiShiYuan006Sub09(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        for tmp_eq in eqs:
            tmp_f = expand(tmp_eq[0] - tmp_eq[1])
            symbs = tmp_f.free_symbols
            if len(symbs) == 4:
                s1, s2, s3 = filter(lambda _: str(_) in ('a', 'b', 'c'), tmp_f.free_symbols)
                s_symb = list(FiniteSet(*tmp_f.free_symbols) - FiniteSet(s1, s2, s3))[0]
                if tmp_f.coeff(s1 * s2):
                    a_symb, b_symb = s1, s2
                    c_symb = s3
                elif tmp_f.coeff(s1 * s3):
                    a_symb, b_symb = s1, s3
                    c_symb = s2
                else:
                    a_symb, b_symb = s3, s3
                    c_symb = s1
            else:
                a_symb, b_symb = tmp_f.free_symbols
                m_value = abs(solve(tmp_f, a_symb + b_symb)[0])
        eq_sets = BaseEqs(
            [eqs[0], eqs[1],
             [cos(str(c_symb).upper()), (a_symb ** 2 + b_symb ** 2 - c_symb ** 2) / (2 * a_symb * b_symb)],
             [s_symb, a_symb * b_symb * sin(str(c_symb).upper()) / 2],
             [sin(str(c_symb).upper()) ** 2 + cos(str(c_symb).upper()) ** 2, 1]])
        self.steps.append(['联立方程组:' + eq_sets.printing(), ''])
        self.steps.append(['得到 ' + BaseEq([cos(str(c_symb).upper()), sympify('-15/17')]).printing(),
                           '; ' + BaseEq([sin(str(c_symb).upper()), '8/17']).printing()])
        self.output.append(['所以%s的最大值等于(2*%s)/17, 当且仅当%s=%s=%s/2时成立' %
                            (new_latex(s_symb), new_latex(m_value), new_latex(a_symb), new_latex(b_symb), str(m_value)),
                            ''])
        max_area = 2 * m_value / 17
        self.output.append(BaseNumber(max_area))
        return self


# 6-10.S=c^{2}-(a-b)^{2}，a^2+b^2=m,求三角形面积的最大值
class ZhiShiYuan006Sub10(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        for tmp_eq in eqs:
            tmp_f = expand(tmp_eq[0] - tmp_eq[1])
            symbs = tmp_f.free_symbols
            if len(symbs) == 4:
                s1, s2, s3 = filter(lambda _: str(_) in ('a', 'b', 'c'), tmp_f.free_symbols)
                s_symb = list(FiniteSet(*tmp_f.free_symbols) - FiniteSet(s1, s2, s3))[0]
                if tmp_f.coeff(s1 * s2):
                    a_symb, b_symb = s1, s2
                    c_symb = s3
                elif tmp_f.coeff(s1 * s3):
                    a_symb, b_symb = s1, s3
                    c_symb = s2
                else:
                    a_symb, b_symb = s3, s3
                    c_symb = s1
            else:
                a_symb, b_symb = tmp_f.free_symbols
                m_value = abs(solve(tmp_f, a_symb ** 2 + b_symb ** 2)[0])
        eq_sets = BaseEqs(
            [eqs[0], eqs[1],
             [cos(str(c_symb).upper()), (a_symb ** 2 + b_symb ** 2 - c_symb ** 2) / (2 * a_symb * b_symb)],
             [s_symb, a_symb * b_symb * sin(c_symb) / 2],
             [sin(str(c_symb).upper()) ** 2 + cos(str(c_symb).upper()) ** 2, 1]])
        self.steps.append(['联立方程组:' + eq_sets.printing(), ''])
        self.steps.append(['得到 ' + BaseEq([cos(str(c_symb).upper()), sympify('-15/17')]).printing(),
                           '; ' + BaseEq([sin(str(c_symb).upper()), '8/17']).printing()])
        self.output.append(['所以%s的最大值等于(2*%s)/17, 当且仅当%s=%s=%s/2时成立' %
                            (new_latex(s_symb), new_latex(m_value), new_latex(a_symb), new_latex(b_symb), str(m_value)),
                            ''])
        max_area = 2 * m_value / 17
        self.output.append(BaseNumber(max_area))
        return self


# 面积最大值
class MianJiZuiDaZhi(BaseFunction):
    CLS = [ZhiShiYuan006Sub01, ZhiShiYuan006Sub02, ZhiShiYuan006Sub03, ZhiShiYuan006Sub04, ZhiShiYuan006Sub05,
           ZhiShiYuan006Sub06, ZhiShiYuan006Sub07, ZhiShiYuan006Sub08, ZhiShiYuan006Sub09, ZhiShiYuan006Sub10]

    def solver(self, *args):
        known_eqs = san_utils.known_triangle_eqs(self.known)
        if known_eqs:
            tmp_args = [known_eqs, ]
        else:
            tmp_args = []
        tmp_args.extend([arg for arg in args])
        solve_r = None
        for cl in MianJiZuiDaZhi.CLS:
            try:
                solve_r = cl(verbose=True)
                solve_r = solve_r.solver(*tmp_args)
                break
            except Exception:
                pass
        if not solve_r:
            raise Exception('Can not solve the question')
        return solve_r


# 7-1 三角形三条边与中线长知3求1
class ZhiShiYuan007Sub01(BaseFunction):
    def solver(self, *args):
        return self


class ZhiShiYuan044(BaseFunction):
    def solver(self, *args):
        return self


# 8-1.由三角函数值得到角度
class ZhiShiYuan008Sub01(BaseFunction):
    def solver(self, *args):
        f = args[0].sympify()
        du_p = r'du(\(\d+?\))'
        m = re.search(du_p, str(f))
        if m:
            du_str = m.group()
            du_sub = sympify(m.groups()[0]) * pi / 180
            f = f.subs(du_str, du_sub)
        self.output.append(BasePoly(f))
        return self


# 8-2.已知角的三角函数的范围求角的范围
class ZhiShiYuan008Sub02(BaseFunction):
    def solver(self, *args):
        return self


# 8-3.正弦/余弦定理求角并确定解的个数
class ZhiShiYuan008Sub03(BaseFunction):
    def solver(self, *args):
        eqs = args[0]
        base_eqs_list = SanJiaoXing.simu_trian_eqs(eqs)
        abc_values_list = []
        for base_eqs in base_eqs_list:
            abc_values = co.solve_poly_eqs(base_eqs)
            abc_values_list.append(abc_values)
        # 合法的边
        abc_values_list = filter(
            lambda _: san_utils.legal_sided(_[0][1]) and san_utils.legal_sided(_[1][1]) and san_utils.legal_sided(
                _[2][1]), abc_values_list)
        # 是否满足两边之和大于第三边
        abc_values_list = filter(lambda _: san_utils.legal_sides((_[0][1], _[1][1], _[2][1])), abc_values_list)
        angles = []
        for abc_values in abc_values_list:
            cos_a_v = sympify('(b**2 + c**2 - a**2)/(2*b*c)').subs(abc_values)
            cos_b_v = sympify('(a**2 + c**2 - a**2)/(2*a*c)').subs(abc_values)
            cos_c_v = acos('(a**2 + b**2 - c**2)/(2*a*b)').subs(abc_values)
            angle_a = acos(cos_a_v)
            angle_b = acos(cos_b_v)
            angle_c = acos(cos_c_v)
            if angle_a + angle_b + angle_c == pi:
                angles.append((angle_a, angle_b, angle_c))
        self.steps.append(['解的个数', new_latex(len(angles))])
        self.output.append(BaseNumber(len(angles)))
        return self


# 8 - 4.已知边a=n,b=m且（n<m)确定角A的范围
class ZhiShiYuan008Sub04(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        line_subs = (('AB', 'c'), ('AC', 'b'), ('BC', 'a'))
        s1, s2 = '', ''
        for l_expr, r_expr in eqs:
            f = (l_expr - r_expr).subs(line_subs)
            if s1:
                s2 = list(f.free_symbols)[0]
                s2_v = solve(f, s2)[0]
            else:
                s1 = list(f.free_symbols)[0]
                s1_v = solve(f, s1)[0]
        if not (s1 and s2 and s1_v and s2_v):
            raise Exception('try error')
        line_values = sorted(((s1, s1_v), (s2, s2_v)), key=itemgetter(1))
        max_value, min_value = line_values
        max_side = sympify(str(max_value[0]).lower())
        max_angle = sympify(str(max_value[0]).upper())
        min_side = sympify(str(min_value[0]).lower())
        min_angle = sympify(str(min_value[0]).upper())
        self.steps.append(['\\because ' + BaseEq([max_side, max_value[1]]).printing(),
                           ', ' + BaseEq([min_side, min_value[1]]).printing()])
        self.steps.append(
            ['\\therefore 由正弦定理 ' + new_latex(max_side / sin(max_angle)), ' = ' + new_latex(min_side / sin(min_angle))])
        min_angle_sin_v = solve(max_side / sin(max_angle) - min_side / sin(min_angle), min_angle)
        coeff = min_angle_sin_v.as_coefficients_dict().items()[1]
        self.steps.append(['即 ' + new_latex(sin(min_angle)), ' = ' + new_latex(min_angle_sin_v)])
        self.steps.append(['\\therefore 0 < ' + new_latex(max_angle) + '< ' + new_latex(pi), ''])
        self.steps.append(
            ['\\therefore ' + new_latex(sin(max_angle)) + ' \\in ', new_latex(Interval(0, 1, left_open=True))])
        self.steps.append(
            ['\\therefore ' + new_latex(sin(min_angle)) + ' \\in ', new_latex(Interval(0, coeff, left_open=True))])
        self.steps.append(['\\because ' + BaseEq([max_side, min_side]).printing(), ','])
        self.steps.append(['\\therefore  ' + BaseEq([max_angle, min_angle]).printing(), ','])
        return self


# 8-5 已知边a=n,b=m且确定角c的范围
class ZhiShiYuan008Sub05(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        line_subs = (('AB', 'c'), ('AC', 'b'), ('BC', 'a'))
        s1, s2 = '', ''
        for l_expr, r_expr in eqs:
            f = (l_expr - r_expr).subs(line_subs)
            if s1:
                s2 = list(f.free_symbols)[0]
                s2_v = solve(f, s2)[0]
            else:
                s1 = list(f.free_symbols)[0]
                s1_v = solve(f, s1)[0]
        if not (s1 and s2 and s1_v and s2_v):
            raise Exception('try error')
        s3 = list(FiniteSet(sympify('a'), sympify('b'), sympify('c')) - FiniteSet(s1, s2))[0]
        cos_angle_s1 = (s2 ** 2 + s3 ** 2 - s1 ** 2) / (2 * s2 * s3)
        cos_angle_s1_v = cos_angle_s1.subs(((s1, s1_v), (s2, s2_v)))
        cos_angle_s2 = (s1 ** 2 + s3 ** 2 - s2 ** 2) / (2 * s1 * s3)
        cos_angle_s2_v = cos_angle_s2.subs(((s1, s1_v), (s2, s2_v)))
        cos_angle_s3 = (s1 ** 2 + s2 ** 2 - s3 ** 2) / (2 * s1 * s2)
        cos_angle_s3_v = cos_angle_s3.subs(((s1, s1_v), (s2, s2_v)))
        ineqs = []
        if len(args) == 2 and isinstance(args[1], str):  # 如果有制定三角形信息
            if args[1].find('锐角') >= 0:
                self.steps.append(['\\because \\vartriangle ABC 为锐角三角形', ''])
                self.steps.append(['\therefore ' + new_latex(cos(str(s1).upper())),
                                   '=' + BaseIneq([cos_angle_s1, '>', '0']).printing()])
                self.steps.append(['\\therefore ' + new_latex(cos(str(s2).upper())),
                                   '=' + BaseIneq([cos_angle_s2, '>', '0']).printing()])
                self.steps.append(['\\therefore ' + new_latex(cos(str(s3).upper())),
                                   '=' + BaseIneq([cos_angle_s3, '>', '0']).printing()])
                ineqs.append(str(cos_angle_s1_v) + '>0')
                ineqs.append(str(cos_angle_s2_v) + '>0')
                ineqs.append(str(cos_angle_s3_v) + '>0')
        self.steps.append(['由三角形不等式得', ''])
        self.steps.append([BaseIneq([s1_v + s2_v, '>', s3]).printing(), ''])
        self.steps.append([BaseIneq([s1_v + s3, '>', s2_v]).printing(), ''])
        self.steps.append([BaseIneq([s2_v + s3, '>', s1_v]).printing(), ''])
        ineqs.append(str(s1_v + s2_v) + '>' + str(s3))
        ineqs.append(str(s1_v + s3) + '>' + str(s2_v))
        ineqs.append(str(s2_v + s3) + '>' + str(s1_v))
        s3_set = co.solve_ineqs(ineqs)
        self.steps.append(['\\therefore ' + new_latex(3) + '的取值范围为: ', new_latex(s3_set)])
        cos_s3_intl = co.func_domain(cos_angle_s3_v, {str(s3): s3_set})
        self.steps.append(['\\therefore ' + new_latex(cos(str(s3).upper())) + '=' + new_latex(cos_angle_s3),
                           '的取值范围为:' + new_latex(cos_s3_intl)])
        s3_angle_intl = solveset('cos(x) > ' + str(cos_s3_intl.left), domain=S.Reals).intersect(
            solveset('cos(x) < ' + str(cos_s3_intl.right), domain=S.Reals))
        self.steps.append(['\\therefore 角 %s' % str(s3).upper(), '的取值范围为' + new_latex(s3_angle_intl)])
        self.output.append(co.to_base_interval(s3_angle_intl))
        return self


# 已知一组角与对边，两个解，求另外一条边的取值范围。--题型
class ZhiShiYuan009Sub01(BaseFunction):
    ANGLES = FiniteSet(sympify('A'), sympify('B'), sympify('C'))

    def solver(self, *args):
        eqs = args[0].sympify()
        text = args[1]
        line_subs = (('AB', 'c'), ('AC', 'b'), ('BC', 'a'))
        s1, s2 = '', ''
        for l_expr, r_expr in eqs:
            f = (l_expr - r_expr).subs(line_subs)
            f = sanjiao_utils.radianed(f)
            symbs = list(f.free_symbols)
            if len(symbs) == 1 and FiniteSet(symbs[0]).is_subset(ZhiShiYuan009Sub01.ANGLES):  # 角
                angle = symbs[0]
                angle_v = solve(f)[0]
            else:
                if s1:
                    s2 = list(filter(lambda s: str(s) in ('a', 'b', 'c'), list(f.free_symbols)))[0]
                    s2_v = solve(f, s2)[0]
                else:
                    s1 = list(filter(lambda s: str(s) in ('a', 'b', 'c'), list(f.free_symbols)))[0]
                    s1_v = solve(f, s1)[0]
        if (not (s1 and s2 and s1_v and s2_v)) or (not angle and angle_v):
            raise Exception('try error')
        if s1_v.is_real:
            one_side = s1
            one_side_v = s1_v
            other_side = s2
            other_side_v = s2_v
        else:
            one_side = s2
            one_side_v = s2_v
            other_side = s1
            other_side_v = s1_v
        if text.find('两个解') >= 0:
            self.steps.append(['\\because 三角形有两解', ''])
            self.steps.append(
                ['\\therefore %s < ' % new_latex(angle_v) + str(other_side).upper(), ' < ' + new_latex(pi - angle_v)])
            self.steps.append(
                ['\\therefore %s < ' % new_latex(sin(angle_v)) + new_latex(sin(str(other_side).upper())), '< 1'])
            self.steps.append(
                ['即: %s <' % new_latex(sin(angle_v)) + new_latex(other_side * sin(str(one_side).upper()) / one_side), ' < 1'])
            ineq1 = str(other_side_v * sin(angle_v) / one_side_v) + '>' + str(sin(angle_v))
            ineq2 = str(other_side_v * sin(angle_v) / one_side_v) + '< 1'
            ineqs = [ineq1, ineq2]
            other_angle_sets = co.solve_ineqs(ineqs)
            self.steps.append(['解上述不等式求得 ' + new_latex(other_side_v), '的取值范围为:' + new_latex(other_angle_sets)])
            self.output.append(BaseSymbolValue({other_side_v: other_angle_sets}))
        elif text.find('一个解') >= 0:
            self.steps.append(['\\because 三角形有一个解', ''])
            if angle_v > pi / 2:
                raise Exception('error')
            self.steps.append(['\\therefore 0<' + new_latex(str(other_side).upper()),
                               '<' + new_latex(angle_v) + '或 %s={90^ \\circ }' % str(other_side).upper()])
            self.steps.append(['\\therefore: 0<' + new_latex(sin(str(other_side).upper())),
                               '<=' + new_latex(sin(angle)) + '或 %s=1' % new_latex(sin(str(other_side).upper()))])
            self.steps.append(['即: 0<' + new_latex(other_side * sin(str(one_side).upper()) / one_side),
                               '<=' + new_latex(sin(str(other_side).upper())) + ' 或 %s=1' % new_latex(
                                   sin(str(other_side).upper()))])
            ineq1 = str(other_side_v * sin(angle_v) / one_side_v) + '>0'
            ineq2 = str(other_side_v * sin(angle_v) / one_side_v) + '<' + str(sin(angle_v))
            ineqs = [ineq1, ineq2]
            other_angle_sets = co.solve_ineqs(ineqs)
            other_angle_sets = other_angle_sets.union(solveset(other_side_v * sin(angle_v) / one_side_v - 1))
            self.steps.append(['解上述不等式求得 ' + new_latex(other_side_v), '的取值范围为:' + new_latex(other_angle_sets)])
            self.output.append(BaseSymbolValue({other_side_v: other_angle_sets}))
        else:
            raise Exception('match error')
        return self


# 11-1.已知两边一角，求某边上三角形的高---题型
class ZhiShiYuan011Sub01(BaseFunction):
    def solver(self, *args):
        eqs = args[0]
        line_subs = (('AB', 'c'), ('AC', 'b'), ('BC', 'a'))
        line = sympify(args[1]).subs(line_subs)
        eq_sets = SanJiaoXing.simu_trian_eqs(eqs)  # 联立方程组
        abc_values_list = []
        for base_eqs in eq_sets:
            abc_values = co.solve_poly_eqs(base_eqs)
            abc_values_list.extend(abc_values)
        # 合法的边
        abc_values_list = filter(
            lambda _: san_utils.legal_sided(_[0][1]) and san_utils.legal_sided(_[1][1]) and san_utils.legal_sided(
                _[2][1]), abc_values_list)
        # 是否满足两边之和大于第三边
        abc_values_list = filter(lambda _: san_utils.legal_sides((_[0][1], _[1][1], _[2][1])), abc_values_list)
        for abc_values in abc_values_list:
            cos_a_v = sympify('(b**2 + c**2 - a**2)/(2*b*c)').subs(abc_values)
            sin_a_v = sqrt(1 - cos_a_v ** 2)
            area = (sympify('1') / 2 * sympify('b') * sympify('c') * sin_a_v).subs(abc_values)
            h = (2 * area / line).subs(abc_values)
            self.steps.append(['高的值为', new_latex(h)])
            self.output.append(BaseNumber(h))
        return self


# 11-2.已知一边一角，求某边上三角形的高-----题型
class ZhiShiYuan011Sub2(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        if len(eqs) != 2:
            raise Exception('Match Type Error')
        eq1, eq2 = eqs
        eq1_f = sanjiao_utils.radianed(eq1[0] - eq1[1])
        eq2_f = sanjiao_utils.radianed(eq2[0] - eq2[1])
        symb1 = list(eq1_f.free_symbols)[0]
        symb2 = list(eq2_f.free_symbols)[0]
        symb1_value = solve(eq1_f)[0]
        symb2_value = solve(eq2_f)[0]
        if symb1 in t_const.ANGLES:
            angle = symb1
            angle_value = symb1_value
            side = symb2
            side_value = symb2_value
        else:
            angle = symb2
            angle_value = symb2_value
            side = symb1
            side_value = symb1_value
        self.steps.append(['h = ' + new_latex(side * sin(angle)), '=' + new_latex(side_value * sin(angle_value))])
        s = side * sin(angle_value)
        self.output.append(BaseNumber(s))
        return self


# 015.已知三角形的三条边长（或者三条边长的比值），求最大内角，最小内角--题型
# 在△ABC中,如果sinA:sinB:sinC=5:6:8,那么此三角形最大角的余弦值是().
class ZhiShiYuan015(BaseFunction):
    def solver(self, *args):
        ratio_eq = ['sin(A):sin(B):sin(C)', '5:6:8']
        text = '最大'
        ratio_l, ratio_r = ratio_eq
        l_items = list(map(sympify, ratio_l.split(':')))
        l_sides = list(map(lambda i: sympify(str(list(i.free_symbols)[0]).lower()), l_items))
        l_latex = new_latex(l_items[0]) + ': ' + new_latex(l_items[1]) + ': ' + new_latex(l_items[2])
        l_sides_latex = new_latex(l_sides[0]) + ': ' + new_latex(l_sides[1]) + ': ' + new_latex(l_sides[2])
        r_items = list(map(sympify, ratio_r.split(':')))
        r_latex = new_latex(r_items[0]) + ': ' + new_latex(r_items[1]) + ': ' + new_latex(r_items[2])
        side_values = zip(l_sides, r_items)
        self.steps.append(['\\because %s=%s' % (l_latex, r_latex), '，'])
        self.steps.append(['\\therefore 由余弦定理可知 %s=%s' % (l_sides_latex, r_latex), ''])
        self.steps.append(['令 %s=%s, %s=%s, %s=%s ' % (
            new_latex(side_values[0][0]), new_latex(side_values[0][1]), new_latex(side_values[1][0]), new_latex(side_values[0][1]),
            new_latex(side_values[2][0]), new_latex(side_values[2][1])), ''])
        sort_sides = sorted(side_values, key=itemgetter(1))
        if text.find('最小') >= 0:
            min_side_value = sort_sides[0]
            cos_min_side = (sort_sides[1][0] ** 2 + sort_sides[2][0] ** 2 - min_side_value[0] ** 2) / \
                           (2 * sort_sides[1][0] * sort_sides[2][0])
            cos_min_side_value = simplify(cos_min_side.subs(side_values))
            self.steps.append(['%s = %s' % (new_latex(cos(str(min_side_value[0]).upper())), new_latex(cos_min_side)),
                               '=' + new_latex(cos_min_side_value)])
            self.steps.append(BaseSymbolValue({cos(str(min_side_value[0]).upper()): cos_min_side_value}))
        else:  # 默认都返回最大角余弦值
            max_side_value = sort_sides[-1]
            cos_max_side = (sort_sides[0][0] ** 2 + sort_sides[1][0] ** 2 - max_side_value[0] ** 2) / \
                           (2 * sort_sides[0][0] * sort_sides[1][0])
            cos_max_side_value = simplify(cos_max_side.subs(side_values))
            self.steps.append(['%s = %s' % (new_latex(cos(str(max_side_value[0]).upper())), new_latex(cos_max_side)),
                               '=' + new_latex(cos_max_side_value)])
            self.steps.append(BaseSymbolValue({cos(str(max_side_value[0]).upper()): cos_max_side_value}))
        return self


# 016.已知一组角与对边求三角形周长的范围--题型
class ZhiShiYuan016(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        if len(eqs) != 2:
            raise Exception('Match Type Error')
        eq1, eq2 = eqs
        f1 = sanjiao_utils.radianed((eq1[0] - eq1[1]).subs(t_const.LINE_SUBS))
        f2 = sanjiao_utils.radianed((eq2[0] - eq2[1]).subs(t_const.LINE_SUBS))
        symbs1 = list(f1.free_symbols)
        symbs2 = list(f2.free_symbols)
        if not (len(symbs1) == 1 and len(symbs2) == 1):
            raise Exception('Match Type Error')
        if str(symbs1[0]).lower() != str(symbs2[0]).lower():
            raise Exception('Type Match Error')
        if symbs1[0] in [sympify('a'), sympify('b'), sympify('c')]:
            side = symbs1[0]
            side_value = solve(f1)[0]
            angle = symbs2[0]
            angle_value = solve(f2)[0]
        else:
            side = symbs2[0]
            side_value = solve(f2)[0]
            angle = symbs1[0]
            angle_value = solve(f1)[0]
        ratio_value = side_value / sin(angle_value)
        other_side1, other_side2 = list(t_const.SIDES - FiniteSet(side))
        other_angle1, other_angle2 = symbols(str(other_side1).upper() + ',' + str(other_side2).upper())
        self.steps.append(['\\because ' + new_latex(side / sin(angle)) + ' = ' + new_latex(
            other_side1 / sin(other_angle1)) + ' = ' + new_latex(other_side2 / sin(other_angle2)), ''])
        self.steps.append(['\\therefore ' + new_latex(other_side1) + '=' + new_latex(ratio_value * sin(other_angle1)),
                           ', ' + new_latex(other_side2) + '=' + new_latex(ratio_value * sin(other_angle2))])
        f1 = collect_const(ratio_value * (sin(other_angle1) + sin(other_angle2)))
        f2 = f1.subs(other_angle2, pi - angle_value - other_angle1)
        f3, _tan_v = sanjiao_utils.aux_ang_f(expand_trig(f2))
        self.steps.append(
            ['\\vartriangle ABC 的周长L=a+b+c=' + new_latex(f1 + side_value),
             '=' + new_latex(f3 + side_value) + '中(\\tan \\theta  = %s)'])
        f3_arg = sanjiao_utils.trig_arg(f3)
        f3_arg_domain = co.func_domain(f3_arg, {str(other_angle1): Interval(0, pi - angle_value)})
        v1 = f3.subs(f3_arg, f3_arg_domain.left)
        v2 = f3.subs(f3_arg, f3_arg_domain.right)
        min_value = min((v1, v2))
        coef = sanjiao_utils.trig_coeff(f3)
        domain = Interval.open(min_value + side_value, coef + side_value)
        self.steps.append(
            ['\\because 0 < ' + new_latex(other_angle1) + '<' + new_latex(pi - angle_value),
             '，%s < %s < %s' % (new_latex(f3_arg_domain.left), new_latex(f3_arg), new_latex(f3_arg_domain.right))])
        self.steps.append(['\\therefore %s < %s <=1' % (new_latex(v1), new_latex(f3 / coef)),
                           '，即 %s< %s <=1' % (new_latex(min_value), new_latex(f3))])
        self.steps.append(['\\vartriangle ABC 的周长的取值范围是', new_latex(domain)])
        self.output.append(co.to_base_interval(domain))
        return self


# 由2r求{ma+nb+pc}/{m1sina+n1sinb+p1c}的值，(其中m/m1=n/n1=p/p1)--题型
class ZhiShiYuan017(BaseFunction):
    # 知道一个角和对边
    # 在△ABC中,A=60°,a=\\sqrt{13},则\\frac{a+b+c}{sinA+sinB+sinC}等于()
    class SubClass01(BaseFunction):
        def solver(self, *args):
            eqs = args[0].sympify()
            f = args[1].sympify()
            if len(eqs) != 2:
                raise Exception('Type Match Error')
            eq1, eq2 = eqs
            f1 = sanjiao_utils.radianed(eq1[0] - eq1[1])
            f2 = sanjiao_utils.radianed(eq2[0] - eq2[1])
            symbs1 = list(f1.free_symbols)
            symbs2 = list(f2.free_symbols)
            if not (len(symbs1) == 1 and len(symbs2) == 1):
                raise Exception('Type Match Error')
            if str(symbs1[0]).upper() != str(symbs2[0]).upper():
                raise Exception('Type Match Error')
            side = sympify(str(symbs1[0]).lower())  # 边变量
            if symbs1[0] == side:  # 如果是关于边的等式
                side_value = solve(f1)[0]
                angle_value = solve(f2)[0]
            else:
                side_value = solve(f2)[0]
                angle_value = solve(f1)[0]
            self.steps.append(['由正弦定理', ''])
            result = side_value / sin(angle_value)
            self.steps.append(
                [new_latex(sympify('a/sin(A)')) + '=' + new_latex(sympify('b/sin(B)')) +
                 '=' + new_latex(sympify('c/sin(C)')), '=' + new_latex(result)])
            self.steps.append(['则 ' + new_latex(f), ' = ' + new_latex(result)])
            self.steps.append(['故答案为：' + new_latex(result), ''])
            self.output.append(BaseNumber(result))
            return self

    # 知道一边，一角 还有三角形面积
    # 在△ABC中,A=60°,b=1,S_{△ABC}=\\sqrt{3},则\\frac{a+b+c}{sinA+sinB+sinC}=()
    class SubClass02(BaseFunction):
        def solver(self, *args):
            eqs = args[0].sympify()
            if len(eqs) != 3:
                raise Exception('Type Match Error')
            f = args[1].sympify()
            eq1, eq2, eq3 = eqs
            f1 = sanjiao_utils.radianed(eq1[0] - eq1[1])
            f2 = sanjiao_utils.radianed(eq2[0] - eq2[1])
            f3 = sanjiao_utils.radianed(eq3[0] - eq3[1])
            area_s = sympify('s')
            if area_s in f1.free_symbols:
                area_value = solve(f1)[0]
            elif area_s in f2.free_symbols:
                area_value = solve(f2)[0]
            elif area_s in f3.free_symbols:
                area_value = solve(f3)[0]
            else:
                raise Exception('Type Match Error')
            self.steps.append(
                ['\\because ' + BaseEq(eq1).printing() + '，' + BaseEq(eq2).printing() + '，其面积为' + new_latex(area_value),
                 ''])
            side_f = list(filter(lambda f_expr: str(list(f_expr.free_symbols)[0]) in ['a', 'b', 'c'], [f1, f2, f3]))[0]
            angle_f = list(filter(lambda f_expr: str(list(f_expr.free_symbols)[0]) in ['A', 'B', 'C'], [f1, f2, f3]))[0]
            side_sym = list(side_f.free_symbols)[0]
            side_value = solve(side_f)[0]
            angle_sym = list(angle_f.free_symbols)[0]
            angle_value = solve(angle_f)[0]
            angle_side_sym = sympify(str(angle_sym).lower())
            other_side_symb = list(FiniteSet(sympify('a'), sympify('b'), sympify('c')) - FiniteSet(side_sym, sympify(
                str(angle_sym).lower())))[0]
            other_side_value = solve(area_value - sympify('1') / 2 * side_value * other_side_symb * sin(angle_value))[0]
            self.steps.append(
                ['\\therefore S=' + new_latex(
                    sympify('1') / 2 * side_sym * other_side_symb * sin(angle_sym)) + '=' + new_latex(area_value),
                 ', 即%s=%s' % (new_latex(other_side_symb), new_latex(other_side_value))])
            tmp_f = side_sym ** 2 + other_side_symb ** 2 - 2 * side_sym * other_side_symb * cos(angle_sym)
            tmp_f_value = tmp_f.subs(((side_sym, side_value), (angle_sym, angle_value),
                                      (other_side_symb, other_side_value)))
            self.steps.append(
                ['\\therefore 由余弦定理得：' + new_latex(angle_side_sym ** 2) + '=' + new_latex(tmp_f) + '=' + new_latex(tmp_f_value),
                 ''])
            angle_side_sym_value = sqrt(tmp_f_value)
            self.steps.append(['\\therefore %s=%s' % (new_latex(angle_side_sym), new_latex(angle_side_sym_value)), '，'])
            result = angle_side_sym_value / sin(angle_value)
            self.steps.append(['由正弦定理得:' + new_latex(sympify('a/sin(A)')) + '=' + new_latex(
                sympify('b/sin(B)')) + '=' + new_latex(sympify('c/sin(C)')) + '=' + new_latex(sympify('2*R')),
                               '=' + new_latex(result)])
            self.steps.append(['则' + new_latex(f) + '=' + new_latex(sympify('2*R')), '=' + new_latex(result)])
            self.output.append(BaseNumber(result))
            return self

    CLS = [SubClass01, SubClass02]

    def solver(self, *args):
        solve_r = None
        for cl in ZhiShiYuan017.CLS:
            try:
                solve_r = cl(verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not solve_r:
            raise 'try fail'
        return solve_r


if __name__ == '__main__':
    pass
